﻿using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace Gmantis.Controls.Extended
{
    [TemplateVisualState(Name = "MouseOver", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Selected", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Disabled", GroupName = "CommonStates"), 
    TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
    public class ColorButton : ContentControl
    {
        // Fields
        internal bool _isLoaded;
        private bool _throwIsMouseOverChanged;
        private bool _throwIsSelectedChanged;
        public static readonly DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(Color), typeof(ColorButton), new PropertyMetadata(Colors.Transparent));
        public static readonly DependencyProperty IsMouseOverProperty = DependencyProperty.Register("IsMouseOver", typeof(bool), typeof(ColorButton), new PropertyMetadata(new PropertyChangedCallback(ColorButton.OnIsMouseOverPropertyChanged)));
        public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register("IsSelected", typeof(bool), typeof(ColorButton), new PropertyMetadata(false, new PropertyChangedCallback(ColorButton.OnIsSelectedPropertyChanged)));

        // Events
        public event RoutedEventHandler Click;
        public event EventHandler<PropertyChangedEventArgs<bool>> IsMouseOverChanged;
        public event EventHandler<PropertyChangedEventArgs<bool>> IsSelectedChanged;

        // Methods
        public ColorButton()
        {
            RoutedEventHandler handler = null;
            this._throwIsSelectedChanged = true;
            this._throwIsMouseOverChanged = true;
            base.DefaultStyleKey = typeof(ColorButton);
            if (handler == null)
            {
                handler = (param0, param1) => this.ChangeVisualStateCommon(false);
            }
            base.Loaded += handler;
            base.MouseEnter += new MouseEventHandler(this.Control_MouseEnter);
            base.MouseLeave += new MouseEventHandler(this.Control_MouseLeave);
            this.SetCustomDefaultValues();
        }

        private void Control_MouseEnter(object sender, MouseEventArgs e)
        {
            if (InputEventArgs.GetPointerType(e) == PointerDeviceType.Mouse)
            {
                this.IsMouseOver = true;
            }
        }

        private void Control_MouseLeave(object sender, MouseEventArgs e)
        {
            if (InputEventArgs.GetPointerType(e) == PointerDeviceType.Mouse)
            {
                this.IsMouseOver = false;
            }
        }

        protected void ChangeVisualStateCommon(bool useTransitions)
        {
            if (!base.IsEnabled)
            {
                VisualStateHelper.GoToState(this, "Disabled", useTransitions);
            }
            if ((base.IsEnabled && !this.IsMouseOver) && !this.IsSelected)
            {
                VisualStateHelper.GoToState(this, "Normal", useTransitions);
            }
            if (base.IsEnabled && this.IsSelected)
            {
                VisualStateHelper.GoToState(this, "Selected", useTransitions);
            }
            if ((base.IsEnabled && this.IsMouseOver) && !this.IsSelected)
            {
                VisualStateHelper.GoToState(this, "MouseOver", useTransitions);
            }
        }

        public override void OnApplyTemplate()
        {
            string str = string.Empty;
            base.OnApplyTemplate();
            this._isLoaded = true;
            if (!string.IsNullOrEmpty(str))
            {
                this._isLoaded = false;
                if ((base.Template != null) && !PlatformIndependent.IsInDesignMode(this))
                {
                    throw new InvalidOperationException(string.Format(CultureInfo.InvariantCulture, "Template cannot be applied to ColorButton.\nDetails: {0}", new object[] { str }));
                }
            }
            else
            {
                this.ChangeVisualStateCommon(false);
            }
        }

        private void OnIsMouseOverChanged(bool oldValue)
        {
            this.UpdateZIndex();
        }

        private static void OnIsMouseOverPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ColorButton sender = d as ColorButton;
            bool oldValue = (bool)e.OldValue;
            sender.OnIsMouseOverChanged(oldValue);
            if ((sender.IsMouseOverChanged != null) && sender._throwIsMouseOverChanged)
            {
                PropertyChangedEventArgs<bool> args = new PropertyChangedEventArgs<bool>
                {
                    OldValue = (bool)e.OldValue,
                    NewValue = (bool)e.NewValue
                };
                sender.IsMouseOverChanged(sender, args);
            }
            sender.ChangeVisualStateCommon(true);
        }

        private void OnIsSelectedChanged(bool oldValue)
        {
            this.UpdateZIndex();
        }

        private static void OnIsSelectedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ColorButton sender = d as ColorButton;
            bool oldValue = (bool)e.OldValue;
            sender.OnIsSelectedChanged(oldValue);
            if ((sender.IsSelectedChanged != null) && sender._throwIsSelectedChanged)
            {
                PropertyChangedEventArgs<bool> args = new PropertyChangedEventArgs<bool>
                {
                    OldValue = (bool)e.OldValue,
                    NewValue = (bool)e.NewValue
                };
                sender.IsSelectedChanged(sender, args);
            }
            sender.ChangeVisualStateCommon(true);
        }

        private void SetCustomDefaultValues()
        {
            base.IsEnabled = true;
            base.MouseLeftButtonDown += delegate(object s, MouseButtonEventArgs a)
            {
                if (this.Click != null)
                {
                    this.Click(this, new RoutedEventArgs());
                }
            };
        }

        private void UpdateZIndex()
        {
            Canvas.SetZIndex(this, (this.IsSelected || this.IsMouseOver) ? 1 : 0);
        }

        // Properties
        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        public bool IsMouseOver
        {
            get { return (bool)GetValue(IsMouseOverProperty); }
            internal set { SetValue(IsMouseOverProperty, value); }
        }

        public bool IsSelected
        {
            get { return (bool)GetValue(IsSelectedProperty); }
            set { SetValue(IsSelectedProperty, value); }
        }
    }
}
